package cn.jly.boot.mp.config;

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.util.StringJoiner;

/**
 * 教程
 * https://mp.weixin.qq.com/s/0Bukv4bFGMWosG8SWWoDDw
 * 主从复制原理
 * 1.slave启动成功连接到master后会发送一个sync命令。
 * 2.Master接到命令启动后台的存盘进程，同时收集所有接收到的用于修改数据集命令。
 * 3.在后台进程执行完毕之后，master将传送整个数据文件到slave,以完成一次完全同步。
 * 4.全量复制：而slave服务在接收到数据库文件数据后，将其存盘并加载到内存中。
 * 5.增量复制：Master继续将新的所有收集到的修改命令依次传给slave,完成同步。
 * 6.但是只要是重新连接master,一次完全同步（全量复制)将被自动执行。
 *
 * 在这里可以为 Redis 设置一些全局配置，比如配置主键的生产策略 KeyGenerator，如不配置会默认使用参数名作为主键
 *
 * @author lanyangji
 * @description redisConfig
 * @date 2020/12/29 下午 4:25
 */
@EnableCaching
@Configuration(proxyBeanMethods = true)
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 覆盖默认配置
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // 替换默认的序列化器
//        template.setStringSerializer(StringRedisSerializer.UTF_8);
//        template.setValueSerializer(StringRedisSerializer.UTF_8);
//        template.setHashKeySerializer(StringRedisSerializer.UTF_8);
//        template.setHashValueSerializer(StringRedisSerializer.UTF_8);
        template.setDefaultSerializer(StringRedisSerializer.UTF_8);
        // 一切奥秘都在这个后置方法中
        // template.afterPropertiesSet();

        return template;
    }

    /**
     * 覆盖默认配置
     *
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        // 替换默认的序列化器
        template.setDefaultSerializer(StringRedisSerializer.UTF_8);
        // template.afterPropertiesSet();

        return template;
    }

    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            /**
             * @param target    目标对象
             * @param method    方法
             * @param params    入参
             * @return
             */
            @Override
            public Object generate(Object target, Method method, Object... params) {
                final StringJoiner stringJoiner = new StringJoiner("-");
                stringJoiner.add(target.getClass().getName());
                stringJoiner.add(method.getName());
                for (Object param : params) {
                    stringJoiner.add(param.toString());
                }
                return stringJoiner.toString();
            }
        };
    }
}
